#include <algorithm>
#include <iostream>
#include <vector>

using namespace std;

struct EDGE {
    int u, v, w;
    EDGE() { u = 0, v = 0, w = 0; }
    EDGE(int u, int v, int w) { this->u = u, this->v = v, this->w = w; }
    bool operator<(const EDGE e) { return w < e.w; }
};

class DSU {
   private:
    vector<int> V;

   public:
    DSU(int n, int STARTS_FROM = 0) : V(n + 1, 0) {
        for (int i = STARTS_FROM; i < n + STARTS_FROM; i++) V[i] = i;
    }

    int find(int v) { return V[v] == v ? v : (V[v] = find(V[v])); }

    void merge(int u, int v) { V[find(u)] = find(v); }

    bool check_connect(int START_FROM = 0) {
        for (int i = START_FROM + 1; i < (int)V.size(); i++)
            if (this->find(i) != this->find(i - 1)) return false;
        return true;
    }
};

const int MAXN = 5e3 + 10;
vector<EDGE> E(0);
int N, M;

int kruskal(vector<vector<EDGE>> &);

int main() {
    cin >> N >> M;

    DSU check(N, 1);
    for (int i = 0; i < M; i++) {
        int u, v, w;
        cin >> u >> v >> w;
        E.push_back(EDGE(u, v, w));
        check.merge(u, v);
    }

    if (!check.check_connect(1)) {
        cout << "orz";
        return 0;
    }

    int tot_w = 0;
    sort(E.begin(), E.end());
    DSU U(N);
    for (auto &e : E) {
        int u = e.u;
        int v = e.v;
        if (U.find(u) == U.find(v))
            continue;
        else {
            tot_w += e.w;
            U.merge(u, v);
        }
    }
    cout << tot_w;
}